package com.edu.exam.entity.examination.online;

import com.edu.exam.enums.SessionEventHandlingStatus;
import com.edu.exam.enums.SessionEventLevel;
import com.edu.exam.enums.SessionEventNotificationStatus;
import com.edu.exam.enums.SessionEventOperationResult;
import com.edu.exam.enums.SessionEventSource;
import com.edu.exam.enums.SessionEventType;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

/**
 * 会话事件实体类
 *
 * <p>会话事件实体用于记录考试会话过程中的各类事件，包括登录事件、
 * 答题事件、系统事件、异常事件等。为会话监控和问题诊断提供详细的事件日志。</p>
 *
 * <p>核心功能：
 * - 事件记录：完整记录会话过程中的各类事件信息
 * - 事件分类：支持多种事件类型和严重级别的分类
 * - 时间戳记录：精确记录事件发生的时间和持续时间
 * - 来源追踪：记录事件的来源和触发条件
 * - 关联分析：支持事件间的关联分析和因果追踪</p>
 *
 * @author 系统生成
 * @version 2.0
 * @since 2025-11-09
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(AuditingEntityListener.class)
public class SessionEvent {

    /**
     * 主键ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 会话ID
     *
     * <p>关联的考试会话ID，标识事件所属的会话。</p>
     */
    @Column(name = "session_id", nullable = false, length = 32)
    private String sessionId;

    /**
     * 学生ID
     *
     * <p>事件关联的学生ID，如果事件与学生相关。</p>
     */
    @Column(name = "student_id", length = 32)
    private String studentId;

    /**
     * 学生姓名
     *
     * <p>事件关联的学生姓名，冗余存储。</p>
     */
    @Column(name = "student_name", length = 100)
    private String studentName;

    /**
     * 事件ID
     *
     * <p>事件的唯一标识符。</p>
     */
    @Column(name = "event_id", nullable = false, length = 32, unique = true)
    private String eventId;

    /**
     * 事件类型
     *
     * <p>事件的类型标识。
     * 支持的类型：LOGIN（登录）、LOGOUT（登出）、ANSWER（答题）、SUBMIT（提交）、
     * SYSTEM（系统）、SECURITY（安全）、NETWORK（网络）、ERROR（错误）等</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "event_type", nullable = false, length = 30)
    private SessionEventType eventType;

    /**
     * 事件子类型
     *
     * <p>事件的子类型，用于更精细的事件分类。</p>
     */
    @Column(name = "event_subtype", length = 50)
    private String eventSubtype;

    /**
     * 事件级别
     *
     * <p>事件的严重级别。
     * 支持的级别：INFO（信息）、WARNING（警告）、ERROR（错误）、CRITICAL（严重）</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "event_level", nullable = false, length = 20)
    private SessionEventLevel eventLevel = SessionEventLevel.INFO;

    /**
     * 事件时间
     *
     * <p>事件发生的精确时间。</p>
     */
    @Column(name = "event_time", nullable = false)
    private LocalDateTime eventTime;

    /**
     * 事件标题
     *
     * <p>事件的标题或简要描述。</p>
     */
    @Column(name = "event_title", nullable = false, length = 200)
    private String eventTitle;

    /**
     * 事件描述
     *
     * <p>事件的详细描述信息。</p>
     */
    @Column(name = "event_description", columnDefinition = "TEXT")
    private String eventDescription;

    /**
     * 事件源
     *
     * <p>事件的来源标识。
     * 如：CLIENT（客户端）、SERVER（服务端）、SYSTEM（系统）、EXTERNAL（外部）</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "event_source", nullable = false, length = 20)
    private SessionEventSource eventSource = SessionEventSource.CLIENT;

    /**
     * 触发条件
     *
     * <p>触发事件的条件或原因。</p>
     */
    @Column(name = "trigger_condition", length = 500)
    private String triggerCondition;

    /**
     * 事件数据
     *
     * <p>事件相关的数据，JSON格式。</p>
     */
    @Column(name = "event_data", columnDefinition = "TEXT")
    private String eventData;

    /**
     * 关联对象ID
     *
     * <p>事件关联的对象ID（如题目ID、答案ID等）。</p>
     */
    @Column(name = "related_object_id", length = 32)
    private String relatedObjectId;

    /**
     * 关联对象类型
     *
     * <p>关联对象的类型。</p>
     */
    @Column(name = "related_object_type", length = 30)
    private String relatedObjectType;

    /**
     * 客户端IP地址
     *
     * <p>事件发生时的客户端IP地址。</p>
     */
    @Column(name = "client_ip_address", length = 45)
    private String clientIpAddress;

    /**
     * 用户代理信息
     *
     * <p>事件发生时的用户代理信息。</p>
     */
    @Column(name = "user_agent", length = 500)
    private String userAgent;

    /**
     * 会话标识
     *
     * <p>事件发生时的会话标识。</p>
     */
    @Column(name = "session_token", length = 128)
    private String sessionToken;

    /**
     * 事件持续时间（毫秒）
     *
     * <p>事件持续的毫秒数。</p>
     */
    @Column(name = "duration_ms")
    private Long durationMs;

    /**
     * 操作结果
     *
     * <p>事件操作的结果。
     * 支持的结果：SUCCESS（成功）、FAILURE（失败）、PARTIAL（部分成功）、TIMEOUT（超时）</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "operation_result", length = 20)
    private SessionEventOperationResult operationResult;

    /**
     * 错误代码
     *
     * <p>事件相关的错误代码。</p>
     */
    @Column(name = "error_code", length = 50)
    private String errorCode;

    /**
     * 错误消息
     *
     * <p>事件相关的错误消息。</p>
     */
    @Column(name = "error_message", columnDefinition = "TEXT")
    private String errorMessage;

    /**
     * 处理状态
     *
     * <p>事件的处理状态。
     * 支持的状态：PENDING（待处理）、PROCESSING（处理中）、RESOLVED（已解决）、IGNORED（已忽略）</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "handling_status", length = 20)
    private SessionEventHandlingStatus handlingStatus = SessionEventHandlingStatus.PENDING;

    /**
     * 处理时间
     *
     * <p>事件处理的时间。</p>
     */
    @Column(name = "handling_time")
    private LocalDateTime handlingTime;

    /**
     * 处理者ID
     *
     * <p>处理事件的操作者ID。</p>
     */
    @Column(name = "handler_id", length = 32)
    private String handlerId;

    /**
     * 处理者姓名
     *
     * <p>处理事件的操作者姓名。</p>
     */
    @Column(name = "handler_name", length = 100)
    private String handlerName;

    /**
     * 处理结果
     *
     * <p>事件处理的结果说明。</p>
     */
    @Column(name = "handling_result", columnDefinition = "TEXT")
    private String handlingResult;

    /**
     * 事件标签
     *
     * <p>事件的标签，JSON格式。
     * 用于事件分类和过滤。</p>
     */
    @Column(name = "event_tags", columnDefinition = "TEXT")
    private String eventTags;

    /**
     * 父事件ID
     *
     * <p>父事件的ID，用于构建事件层级关系。</p>
     */
    @Column(name = "parent_event_id", length = 32)
    private String parentEventId;

    /**
     * 根事件ID
     *
     * <p>根事件的ID，用于构建事件树。</p>
     */
    @Column(name = "root_event_id", length = 32)
    private String rootEventId;

    /**
     * 事件链ID
     *
     * <p>事件链的ID，用于关联一系列相关事件。</p>
     */
    @Column(name = "event_chain_id", length = 32)
    private String eventChainId;

    /**
     * 是否需要通知
     *
     * <p>标识是否需要发送事件通知。</p>
     */
    @Column(name = "notification_required", nullable = false)
    private Boolean notificationRequired = false;

    /**
     * 通知状态
     *
     * <p>通知的发送状态。</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "notification_status", length = 20)
    private SessionEventNotificationStatus notificationStatus = SessionEventNotificationStatus.NOT_REQUIRED;

    /**
     * 通知时间
     *
     * <p>通知的发送时间。</p>
     */
    @Column(name = "notification_time")
    private LocalDateTime notificationTime;

    // ===== 审计字段 =====

    /**
     * 创建时间
     */
    @CreatedDate
    @Column(name = "created_time", nullable = false, updatable = false)
    private LocalDateTime createdTime;

}